/*
 * @(#)DialogKalender.java
 * 1.0, 2013-01-24
 */
package de.hdm.gruppenkalender.team04.gui;

import de.hdm.gruppenkalender.team04.data.Kalender;
import de.hdm.gruppenkalender.team04.data.Kategorie;
import de.hdm.gruppenkalender.team04.data.Person;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.rmi.RemoteException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * Aufbau des Kalender Dialog mit den diversen Elementen.
 *
 * @author Mathias Bendel (mb167)
 * @author Björn Fichnter (bf023)
 * @author Stefan Hettich (sh176)
 * @author René Kugel (rk044)
 * @author Mark Leonberger (ml072)
 * @author Marta Przybylski (mp070)
 *
 * @version 1.0, 2013-01-24
 *
 */
public class DialogKalender extends JDialog {

    // Kalender der gestzt wird, wenn Bearbeiten-Fenster geöffnet wird.
    Kalender kalender;
    Vector<Integer> zugriffsberechtigte = new Vector<Integer>();
    JTextField txtBezeichnung;
    JComboBox cbxBerechtigte;
    JComboBox cbxBesitzer;
    DefaultComboBoxModel comboModelBerechtigte;
    JList listBerechtigte;
    JButton btnBerechtigteLoeschen;
    JButton btnBerechtigteHinzufuegen;
    JButton buttonSpeichern;
    DefaultListModel listModelBerechtigte;
    HashMap<String, Kategorie> hashMapKategorie;
    HashMap<String, Kalender> hashMapKalender;
    HashMap<String, Person> hashMapBesitzer;
    HashMap<String, Person> hashMapBerechtigte;
    HashMap<String, Person> hashMapBerechtigteHinzugefuegt;
    HauptFenster hauptFenster;
    InterfaceClient ic;
    // Aktueller System-Nutzer, ist null, falls Administrator angemeldet.
    Person aktuellerNutzer;
    private final static String STR_Bezeichnung =
            "Bitte geben Sie die Bezeichnung ein.";

    /**
     * Konstruktor, der das aufrufende Hauptfenster übergibt.
     * 
     * @param hf
     */
    public DialogKalender(HauptFenster hf) {
        this(hf, null);
    }

    /**
     * Konstruktor, der das aufrufende Hauptfenster und den zu
     * bearbeitenden Kalender übergibt.
     * <p>
     * Der aktuelle Nutzer wird aus dem HauptFenster ausgelesen und
     * das Erstellen der Elemente wird angestoßen.
     * 
     * @param hf
     * @param kalender
     */
    public DialogKalender(HauptFenster hf, Kalender kalender) {
        super(hf, "", true);
        this.hauptFenster = hf;
        this.ic = InterfaceClient.interfaceClient();
        this.aktuellerNutzer = hauptFenster.getAktuellerNutzer();
        this.kalender = kalender;
        this.erstelleElemente();
    }

    /**
     * erstellt das Hauptpanel
     */
    public void erstelleElemente() {
        if (kalender == null) {
            this.setTitle("Kalender anlegen");
        } else {
            try {
                this.setTitle("Kalender '" + kalender.getBezeichnung() +
                        "' bearbeiten");
            } catch (RemoteException ex) {
                Logger.getLogger(DialogKalender.class.getName()).log(
                        Level.SEVERE,
                        null, ex);
                this.setTitle("Kalender bearbeiten");
            }
        }

        JPanel hauptPanel = erstelleHauptPanel();
        if (hauptPanel != null) {
            this.add(hauptPanel);

            this.setLocation(50, 50);
            this.setResizable(false);

            this.pack();
            this.setVisible(true);
        }
    }

    /**
     * füllt das Hauptpanel mit GUI-Elementen und befüllt diese mit Werten
     * 
     * @return  JPanel  hauptPanel
     */
    public JPanel erstelleHauptPanel() {
        JPanel hauptPanel = new JPanel();

        // GridLayout mit Abstand zwischen den Elementen.
        hauptPanel.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.anchor = GridBagConstraints.LINE_START;
        c.insets = new Insets(5, 5, 5, 5);

        // Abstand nach außen erzeugen.
        hauptPanel.setBorder(new EmptyBorder(10, 10, 10, 10));

        c.gridx = 0;
        c.gridy = 0;
        c.gridwidth = 1;
        hauptPanel.add(new JLabel("Titel:", JLabel.RIGHT), c);
        c.gridx = 1;
        c.gridy = 0;
        c.gridwidth = 2;
        txtBezeichnung = this.erstelleTextFeld(STR_Bezeichnung);
        hauptPanel.add(txtBezeichnung, c);

        /**
         * Wenn Administrator angemeldet ist, muss ein Ersteller gewählt werden.
         */
        int gridLayoutParam = 0;
        if (aktuellerNutzer == null) {
            /**
             * ComboBox und Label für Ersteller.
             */
            gridLayoutParam = 1;
            c.gridx = 0;
            c.gridy = 1;
            c.gridwidth = 1;
            hauptPanel.add(new JLabel("Ersteller:", JLabel.RIGHT), c);
            String ausgewaehlt = "";
            Vector<Person> besitzers = ic.ermittleAllePersonen();
            if (besitzers.size() < 1) {
                // Wenn es keine Personen gibt.
                JOptionPane.showMessageDialog(hauptFenster,
                        "Es existieren keine Personen.\n Erstellen Sie " +
                        "zunächst eine Person.",
                        "Fehler im Datenbestand",
                        JOptionPane.ERROR_MESSAGE);
                return null;
            }
            Vector<String> strBesitzer = new Vector<String>();
            hashMapBesitzer = new HashMap<String, Person>();
            for (Person ersteller : besitzers) {
                String name = "";
                try {
                    name = ersteller.ermittleIdentifikationsName();
                    if (kalender != null) {
                        if (ersteller.getPersonId() == kalender.getBesitzerId()) {
                            ausgewaehlt = name;
                        }
                    }
                } catch (RemoteException ex) {
                    Logger.getLogger(DialogTermin.class.getName()).
                            log(Level.SEVERE, null, ex);
                }
                strBesitzer.add(name);
                hashMapBesitzer.put(name, ersteller);
            }
            cbxBesitzer = new JComboBox(strBesitzer);
            c.gridx = 1;
            c.gridy = 1;
            c.gridwidth = 2;
            hauptPanel.add(cbxBesitzer, c);

            if (kalender != null) {
                cbxBesitzer.setSelectedItem(ausgewaehlt);
            }
        }

        /**
         * Teilnehmer-Bereich hinzufügen um Termine in gepflegtem Kalender für diese einsehbar zu machen
         * Neue Teilnehmer werden über ComboBox hinzugefügt
         * und in der Liste angezeigt und dort ggf. wieder gelöscht.
         */
        c.gridx = 0;
        c.gridy = 2 + gridLayoutParam;
        c.gridwidth = 1;
        hauptPanel.add(new JLabel("Sichtbar für:", JLabel.RIGHT), c);

        Vector<Person> berechtigte = ic.ermittleAllePersonen();
        if (berechtigte.size() < 1) {
                // Wenn es keine Personen gibt.
                JOptionPane.showMessageDialog(hauptFenster,
                        "Es existieren keine Personen.\n Erstellen Sie " +
                        "zunächst eine Person.",
                        "Fehler im Datenbestand",
                        JOptionPane.ERROR_MESSAGE);
                return null;
            }
        if (kalender != null) {
            try {
                zugriffsberechtigte = kalender.getZugriffsberechtigteId();
            } catch (RemoteException ex) {
                Logger.getLogger(DialogKalender.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
        }
        comboModelBerechtigte = new DefaultComboBoxModel();
        hashMapBerechtigte = new HashMap<String, Person>();
        for (Person person : berechtigte) {
            try {
                if (!zugriffsberechtigte.contains(person.getPersonId())) {
                    String name = person.ermittleIdentifikationsName();
                    comboModelBerechtigte.addElement(name);
                    hashMapBerechtigte.put(name, person);
                }
            } catch (RemoteException ex) {
                Logger.getLogger(DialogKalender.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
        }
        cbxBerechtigte = new JComboBox(comboModelBerechtigte);
        c.gridx = 1;
        c.gridy = 2 + gridLayoutParam;
        c.gridwidth = 1;
        hauptPanel.add(cbxBerechtigte, c);

        hashMapBerechtigteHinzugefuegt = new HashMap<String, Person>();
        listModelBerechtigte = new DefaultListModel();
        for (int personId : zugriffsberechtigte) {
            Person p = ic.ermittlePersonViaSchluessel(personId);
            String name = "";
            try {
                name = p.ermittleIdentifikationsName();
            } catch (RemoteException ex) {
                Logger.getLogger(DialogTermin.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
            listModelBerechtigte.addElement(name);
            hashMapBerechtigteHinzugefuegt.put(name, p);
        }

        btnBerechtigteHinzufuegen = new JButton("Berechtigten hinzufügen");
        btnBerechtigteHinzufuegen.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                String t = String.valueOf(cbxBerechtigte.getSelectedItem());
                comboModelBerechtigte.removeElement(t);

                if (comboModelBerechtigte.getSize() < 1) {
                    cbxBerechtigte.setEnabled(false);
                    btnBerechtigteHinzufuegen.setEnabled(false);
                }

                listModelBerechtigte.addElement(t);
                sortiereTeilnehmerListe();
                hashMapBerechtigteHinzugefuegt.put(t, hashMapBerechtigte.get(t));
                int index = listModelBerechtigte.indexOf(t);
                listBerechtigte.setSelectedIndex(index);
                listBerechtigte.ensureIndexIsVisible(index);
            }
        });
        c.gridx = 2;
        c.gridy = 2 + gridLayoutParam;
        c.gridwidth = 1;
        hauptPanel.add(btnBerechtigteHinzufuegen, c);

        listBerechtigte = new JList(listModelBerechtigte);
        listBerechtigte.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        listBerechtigte.setVisibleRowCount(5);
        listBerechtigte.setSize(0, 100);
        listBerechtigte.addListSelectionListener(new ListSelectionListener() {

            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting() == false) {
                    if (listBerechtigte.getSelectedIndex() == -1) {
                        btnBerechtigteLoeschen.setEnabled(false);
                    } else {
                        btnBerechtigteLoeschen.setEnabled(true);
                    }
                }
            }
        });
        JScrollPane listScrollPane = new JScrollPane(listBerechtigte);
        listScrollPane.setPreferredSize(new Dimension(256, 100));
        c.gridx = 1;
        c.gridy = 3 + gridLayoutParam;
        c.gridwidth = 1;
        hauptPanel.add(listScrollPane, c);
        btnBerechtigteLoeschen = new JButton("Berechtigten löschen");
        btnBerechtigteLoeschen.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                int index = listBerechtigte.getSelectedIndex();
                String t = listModelBerechtigte.get(index).toString();
                listModelBerechtigte.remove(index);
                hashMapBerechtigteHinzugefuegt.remove(t);

                listBerechtigte.setSelectedIndex(0);
                listBerechtigte.ensureIndexIsVisible(index);

                comboModelBerechtigte.addElement(t);
                if (comboModelBerechtigte.getSize() > 0) {
                    cbxBerechtigte.setEnabled(true);
                    btnBerechtigteHinzufuegen.setEnabled(true);
                }
                sortiereTeilnehmerCombo();
                cbxBerechtigte.setSelectedIndex(0);
            }
        });
        btnBerechtigteLoeschen.setEnabled(false);
        c.gridx = 2;
        c.gridy = 3 + gridLayoutParam;
        c.gridwidth = 1;
        hauptPanel.add(btnBerechtigteLoeschen, c);

        /**
         * Speichern-Button hinzufügen.
         */
        buttonSpeichern = new JButton("Speichern");
        buttonSpeichern.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                if (!txtBezeichnung.getText().equals("") && !txtBezeichnung.
                        getText().equals(STR_Bezeichnung)) {
                    int besitzerId = ermittleBesitzerId();

                    Kalender k = null;
                    if (kalender == null) {
                        k = ic.erstelleKalender(
                                txtBezeichnung.getText(),
                                besitzerId,
                                ermittleBerechtigteIds(besitzerId));
                    } else {
                        k = ic.bearbeiteKalender(kalender,
                                txtBezeichnung.getText(),
                                besitzerId,
                                ermittleBerechtigteIds(besitzerId));
                    }
                    hauptFenster.erstelleKalenderVerwaltung();
                    hauptFenster.aktualisiereSwingKomponenten();
                    setVisible(false);
                    dispose();
                    try {
                        JOptionPane.showMessageDialog(hauptFenster,
                                "Kalender '" + k.getBezeichnung() +
                                "' erfolgreich gespeichert!");
                        hauptFenster.setzteListIndex(k.
                                ermittleIdentifikationsName());
                    } catch (RemoteException ex) {
                        Logger.getLogger(DialogKalender.class.getName()).
                                log(Level.SEVERE, null, ex);
                    }
                } else {
                    zeigeErrorDialog();
                }
            }
        });

        c.gridx = 1;
        c.gridy = 4 + gridLayoutParam;
        c.gridwidth = 2;
        hauptPanel.add(buttonSpeichern, c);

        return hauptPanel;
    }

    /**
     * sotieren der Teilnehmer-JList.
     */
    public void sortiereTeilnehmerListe() {
        Vector<String> list = new Vector<String>();
        for (int i = 0; i < listModelBerechtigte.getSize(); i++) {
            list.add(listModelBerechtigte.getElementAt(i).toString());
        }

        Collections.sort(list);

        for (int i = 0; i < listModelBerechtigte.getSize(); i++) {
            listModelBerechtigte.setElementAt(list.get(i), i);
        }
    }

    /**
     * sortieren der Teilnehmer-JComboBox.
     */
    public void sortiereTeilnehmerCombo() {
        Vector<String> list = new Vector<String>();
        int size = comboModelBerechtigte.getSize();
        for (int i = 0; i < size; i++) {
            list.add(comboModelBerechtigte.getElementAt(i).toString());
        }

        Collections.sort(list);

        comboModelBerechtigte.removeAllElements();
        for (int i = 0; i < size; i++) {
            comboModelBerechtigte.addElement(list.get(i));
        }
    }

    /**
     * erstellen des JTextField
     * 
     * @param   platzhalter
     * @return  JTextField  textFeld
     */
    public JTextField erstelleTextFeld(String platzhalter) {
        JTextField textFeld = new JTextField();

        if (kalender == null) {
            textFeld.setText(platzhalter);
        } else {
            try {
                if (platzhalter.equals(STR_Bezeichnung)) {
                    textFeld.setText(kalender.getBezeichnung());
                }
            } catch (RemoteException ex) {
                Logger.getLogger(DialogKalender.class.getName()).log(
                        Level.SEVERE,
                        null, ex);
            }
        }

        textFeld.addFocusListener(new TextFeldFocusListener(platzhalter, true));

        return textFeld;
    }

    /**
     * Ermittelt die Id des Besitzers des Kalenders
     * Unterscheidet sich je nachdem, ob Nutzer oder Administrator eingeloggt
     * ist.
     *
     * @return  int Besitzer-Id
     */
    private int ermittleBesitzerId() {
        try {
            if (aktuellerNutzer == null) {
                // Admin-Ansicht. Ersteller in Form gewählt.
                return hashMapBesitzer.get(cbxBesitzer.getSelectedItem().
                        toString()).getPersonId();

            } else {
                // Nutzer angemeldet => Dessen ID.
                return aktuellerNutzer.getPersonId();
            }
        } catch (RemoteException ex) {
            Logger.getLogger(DialogTermin.class.getName()).
                    log(Level.SEVERE, null, ex);
        }

        return 0;
    }

    /**
     * Liest die Zugriffsberechtigten aus dem Formular aus und gibt sie in
     * einem Vector<Integer> zurück.
     *
     * @param   erstellerId
     * @return  Vector<Integer> Berechtigten-IDs
     */
    private Vector<Integer> ermittleBerechtigteIds(int erstellerId) {
        Vector<Integer> berechtigteIds = new Vector<Integer>();
        for (int i = 0; i < listModelBerechtigte.getSize(); i++) {
            Person p = hashMapBerechtigteHinzugefuegt.get(
                    listModelBerechtigte.get(i).toString());
            try {
                berechtigteIds.add(p.getPersonId());
                System.out.println(p.getPersonId());
            } catch (RemoteException ex) {
                Logger.getLogger(DialogTermin.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
        }

        /**
         * Prüfen, ob Besitzer bereits Zugriffsberechtigter ist,
         * sonst ebenfalls hinzufügen.
         */
        if (!berechtigteIds.contains(erstellerId)) {
            berechtigteIds.add(erstellerId);
        }

        return berechtigteIds;
    }

    /**
     * Zeigt einen Fehlerdialog, der auf Fehler bei der Formulareingabe
     * aufmerksam machen.
     */
    public void zeigeErrorDialog() {
        JOptionPane.showMessageDialog(DialogKalender.this,
                "Das Feld 'Bezeichnung' darf nicht leer sein.",
                "Fehler beim Speichern",
                JOptionPane.ERROR_MESSAGE);
    }
}
